package com.farm.wda;

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.log4j.Logger;

import com.farm.wda.domain.DocTask;
import com.farm.wda.impl.WdaAppImpl;
import com.farm.wda.util.AppConfig;
import com.farm.wda.util.FileUtil;
import com.farm.wda.wcpservice.WcpServer;

/**
 * 文档转换调度器
 * 
 * @author wangdong
 *
 */
public class ConvertFactory implements Runnable {
	private static final Logger log = Logger.getLogger(ConvertFactory.class);

	@Override
	public void run() {
		log.info("WDA[ConvertFactory]------------start...");
		long outTime = Long.valueOf(AppConfig.getString("config.conver.timeout"));
		log.info("WDA[ConvertFactory]------------outtime:" + outTime + "ms");
		while (true) {
			sleep();
			if (!WdaAppImpl.tasks.isEmpty()) {
				DocTask task = null;
				try {
					initOfficeConvert();
					task = getStartTask();
					logStart(task);
					{// 启用一个带超时判断的转换任务
						ExecutorService executor = Executors.newSingleThreadExecutor();
						FutureTask<Boolean> future = new FutureTask<Boolean>(new ConvertTask(task));
						try {
							//执行转换任务
							executor.execute(future);
							// 在一定时间内执行该任务
							future.get(outTime, TimeUnit.MILLISECONDS); // 取得结果，同时设置超时执行时间为5秒。同样可以用future.get()，不设置执行超时时间取得结果
							FileUtil.wirteLog(task.getLogFile(), "[success]" + task.getTargetFile().getName());
							WcpServer.getInstance().FileConvertSuccessEvent(task);
							log.info("WDA[fileConvert][success]------------convert success！" + task.getFile().getName());
						} catch (TimeoutException e) {
							logError(task, e);
							//如果超时执行则重启openoffice服务
							Beanfactory.startOpenOfficeServer();
							future.cancel(true);
						} finally {
							executor.shutdown();
						}
					}
				} catch (Exception e) {
					logError(task, e);
				} finally {
					WdaAppImpl.tasks.remove();
				}
			}
		}
	}

	/**
	 * 获得一个正要启动的任务
	 * 
	 * @return
	 */
	private DocTask getStartTask() {
		DocTask task = WdaAppImpl.tasks.element();
		// 2标识任务处理中
		task.setState("2");
		task.setStime(new Date());
		return task;
	}

	/**
	 * 日志--开始转换
	 * 
	 * @param task
	 */
	private void logStart(DocTask task) {
		FileUtil.wirteLog(task.getLogFile(), "[start] file key is\"" + task.getKey() + "\"" + "start task!-"
				+ task.getFileTypeName() + " to " + task.getTargetFile().getName());
		WcpServer.getInstance().FileConvertStartingEvent(task);
	}

	/**
	 * 日志--转换异常
	 * 
	 * @param task
	 */
	private void logError(DocTask task, Exception e) {
		try {
			FileUtil.wirteLog(task.getLogFile(), "[error]" + e.getClass() + ":" + (e.getMessage() != null ? e.getMessage() : ""));
			log.error("WDA[error]------------convert fail![key:" + task.getKey() + ",authid:" + task.getAuthid() + "]："
					+ e.getClass() + ":" + (e.getMessage() != null ? e.getMessage() : ""), e);
			WcpServer.getInstance().FileConvertErrorEvent(task,e.getMessage());
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}

	/**
	 * 睡眠1秒钟
	 */
	private void sleep() {
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e1) {
		}
	}

	/**
	 * 判断openoffice的服务是否启动，如果没有启动就启动一下
	 */
	private void initOfficeConvert() {
		if (!Beanfactory.isStartByOpenofficeServer()) {
			Beanfactory.startOpenOfficeServer();
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				log.error(e+e.getMessage(), e);
			}
		}
	}
}
